<?php
/**
 * Created by PhpStorm.
 * User: Keter
 * Date: 2016/7/28
 * Time: 20:58
 */
class Base
{
    /**
     * 是否使用Redis保存日志
     * @var bool
     */
    public $isRedisLog = true;

    public function isRedisLog($enabled = true)
    {
        $this->isRedisLog = $enabled ? true : false;
    }

    /**
     * Function printData($status, $desc, $data)
     * 输出数据信息
     *
     * @access public
     * @param  int  $status 状态值
     * @param  text $msg 错误信息
     * @param  text $data 真正返回数据信息
     * @return true
     */
    public function printData($status, $msg = "", $data = "")
    {
        $msg = array('status' => (int)$status, 'desc' => $msg, 'data' => $data);
        $msg = json_encode($msg, JSON_UNESCAPED_UNICODE);

        echo $msg;
        exit(0);
    }

    /**
     * 返回成功
     * @param $desc
     * @param $data
     * @param array $vars
     */
    public function returnData($desc, $data, array $vars = array())
    {
        $logData = RedisLog::info($desc, $data, $vars);
        $this->writeRedisLog($logData);
        $this->printData(1, $logData['msg'], $data);
        exit(0);
    }

    /**
     * 返回错误
     * @param $status
     * @param $desc
     * @param array $vars
     * @param $data
     */
    public function returnError($desc, $status = -1, array $vars = array(), $data = "")
    {
        $logData = RedisLog::error($desc, $data, $vars);
        $this->writeRedisLog($logData);
        $this->printData($status, $logData['msg'], $data);
        exit(0);
    }

    /**
     * 抛出异常
     * @param $desc
     * @param int $status
     * @param array $vars
     * @param string $data
     * @throws Exceptoin
     */
    public function throwError($desc, $status = -1)
    {
        throw new Exception($desc, $status);
        return false;
    }

    /**
     * 记录警告信息
     * @param $desc
     * @param $data
     * @param array $vars
     */
    public function logWarning($desc, $data = array(), array $vars = array())
    {
        $logData = RedisLog::warning($desc, $data, $vars);
        $this->writeRedisLog($logData);
        $this->w($logData['msg']);
    }

    /**
     * 写入Redis日志
     * @param $logData
     */
    public function writeRedisLog($logData)
    {
        $redis = $this->redis('server_log');

        if (is_object($redis)) {
            $logData['msg'] = null;
            unset($logData['msg']);
            $logData = json_encode($logData, JSON_UNESCAPED_UNICODE);
            $redis->lpush('xLog', $logData);
        }
    }

    /**
     * 目录检查
     * @param $dir
     * @return bool
     */
    public function checkDir($dir)
    {
        $dir = pathFormat($dir);

        if (!is_dir($dir)) {
            if (!@mkdir($dir, 0755, true)) {
                return '数据目录不存在';
            }
        }

        if (!is_writable($dir)) {
            return '数据目录不可写';
        }

        return null;
    }

    /**
     * 写文件
     * @param $file
     * @param $content
     * @return bool
     */
    public function writeFile($file, $content, $opmode = 'wb')
    {
        if (!is_file($file)) {
            if (!is_writable(dirname($file))) {
                @mkdir(dirname($file), 0755);
            }
        }

        $fo = @fopen($file, $opmode);
        if ($fo === false) {
            $this->e('要写入的文件打开失败', $file);
            return false;
        }

        if (!is_writable($file)) {
            $this->e('文件不可写', $file);
            return false;
        }

        $locked = flock($fo, LOCK_EX | LOCK_NB);
        if ($locked === false) {
            $this->e('文件锁定失败', $file);
            return false;
        }

        if (!@fwrite($fo, $content)) {
            $this->e('文件写入失败', $file);
            return false;
        }

        flock($fo, LOCK_UN);
        @fclose($fo);

        return true;
    }

    /**
     * Function exec_run()
     * 运行流程
     */
    public function exec_logic()
    {
        $this->init();
        if ($this->before()) {
            $this->logic();
        }
        $this->after();
    }

    /**
     * Function d($msg)
     * 根据等级写入日志文件
     *
     * @access public
     * @param  text $msg 内容
     * @return true
     */
    public function d($desc, $data = array(), array $vars = array())
    {
        if ($this->isRedisLog){
            $this->i($desc, $data, $vars);
            //GlobalConfig::$logger->debug($this->tag, $desc);
        } else {
            $this->writeFileLog(RedisLog::info($desc, $data, $vars), 'debug');
        }
    }

    public function i($desc, $data = array(), array $vars = array())
    {
        if ($this->isRedisLog){
            $logData = RedisLog::info($desc, $data, $vars);
            $this->writeRedisLog($logData);
            ///GlobalConfig::$logger->info($this->tag, $desc);
        } else {
            $this->writeFileLog(RedisLog::info($desc, $data, $vars), 'info');
        }
    }

    public function w($desc, $data = array(), array $vars = array())
    {
        if ($this->isRedisLog) {
            $logData = RedisLog::warning($desc, $data, $vars);
            $this->writeRedisLog($logData);
            //GlobalConfig::$logger->warn($this->tag, $desc);
        } else {
            $this->writeFileLog(RedisLog::warning($desc, $data, $vars), 'warning');
        }
    }

    public function e($desc, $data = array(), array $vars = array())
    {
        if ($this->isRedisLog){
            $logData = RedisLog::error($desc, $data, $vars);
            $this->writeRedisLog($logData);
            //GlobalConfig::$logger->error($this->tag, $desc);
        } else {
            $this->writeFileLog(RedisLog::error($desc, $data, $vars), 'error');
        }
    }

    public function f ($desc, $data = array(), array $vars = array())
    {
        if ($this->isRedisLog) {
            $this->e($desc, $data, $vars);
            //GlobalConfig::$logger->fatal($this->tag, $desc);
        } else {
            $this->writeFileLog(RedisLog::error($desc, $data, $vars), 'fatal');
        }
    }

    /**
     * 写入文件日志
     * @param $logData
     */
    public function writeFileLog($logData, $method)
    {
        if (method_exists(GlobalConfig::$logger, $method)) {
            $logData['msg'] = null;
            unset($logData['msg']);
            $logData = json_encode($logData, JSON_UNESCAPED_UNICODE);
            GlobalConfig::$logger->$method($this->tag, $logData);
        }
    }

    /**
     * 将数组中的数字字符串转换成数字类型
     * @param $data
     * @param array $exceptKeys
     * @param bool $recursive
     * @return mixed
     */
    public function formatNumber($data, array $exceptKeys = array(), $recursive = true)
    {
        foreach ($data as $key => $value) {
            if (is_array($value)) {
                if ($recursive) {
                    $data[$key] = $this->formatNumber($value, $exceptKeys, $recursive);
                } else {
                    continue;
                }
            } else{
                if (!in_array($key, $exceptKeys)
                    && is_numeric($value)
                    && gettype($value) == 'string'
               ) {
                    if (strstr($value, '.')) {
                        $data[$key] = (float)$value;
                    } else {
                        $data[$key] = (integer)$value;
                    }
                }
            }
        }

        return $data;
    }
}